package model;

import protocol.JS_2017.JS_ATL_2017Cmd;
import utils.ExceptionUtils;
import utils.HexUtils;
import utils.StringUtils;

import java.util.List;

/**
 *
 * 江苏
 * T/JSATL 12-2017
 * 参见：苏标终端与外设通讯协议规范
 *
 */
public class ProtocolJS_2017Model extends IModel {

    private final static int Protocol_Analysis = 0;//数据内容解析
    private final static int Protocol_Check = 1;//数据校验

    public final static byte DEVICE_DMS = 0x65;
    public final static byte DEVICE_ADAS = 0x64;

    @Override
    protected void initTypes(List<String> list) {
        list.add(Protocol_Analysis,"数据内容解析");
        list.add(Protocol_Check,"数据校验");
    }

    @Override
    public String change(String input) {
        try{

            input = StringUtils.formatProtocol(input);

            byte[] list = HexUtils.toHexBytes(input);
            JS_ATL_2017Cmd cmd = new JS_ATL_2017Cmd(list);

            if (getType() == Protocol_Check){
                return checkProtocolStr(cmd,list);
            }

            switch (cmd.order()){
                case 0x2F:
                    return handleCmd2F(cmd);
                case 0x31:
                    return handleCmd31(cmd);
                case 0x36:
                    return handleCmd36(cmd);
                case 0x50:
                    return handleCmd50(cmd);
                case 0x51:
                    return handleCmd51(cmd);
                default:
                    return "苏标:未匹配的命令字"+(cmd.order()&0xFF);
            }
        }catch (Exception e){
            return "数据校验失败\n"+ ExceptionUtils.getExceptionMsg(e);
        }
    }

    private String checkProtocolStr(JS_ATL_2017Cmd cmd, byte[] data) {
        StringBuilder builder = new StringBuilder();

        if (data[0] != 0x7e){
            builder.append("数据包头错误(正常包头：7e)："+HexUtils.toHexStr(new byte[]{data[0],data[1]}));
            builder.append("\r\n");
            return builder.toString();
        }

        if (data[data.length - 1] != 0x7e){
            builder.append("数据包尾错误(正常包尾：7e)："+HexUtils.toHex(data[data.length - 1],1));
            builder.append("\r\n");
            return builder.toString();
        }

        builder.append("命令字："+cmd.readOrder());
        builder.append("\r\n");

        builder.append("流水号："+cmd.seq());
        builder.append("\r\n");

        builder.append("数据区："+cmd.readBCD(cmd.leftSize()));
        builder.append("\r\n");

//        int xor = cmd.xor();
//        builder.append("效验位："+HexUtils.toHex(xor));
//        builder.append("\r\n");
//
//        int checkXOR = cmd.reCheckXOR();
//        builder.append("检验位校验("+(xor == checkXOR?"数据正常":"数据异常")+")："+ HexUtils.toHex(checkXOR));
//        builder.append("\r\n");

        return builder.toString();
    }

    private String handleCmd31(JS_ATL_2017Cmd cmd) {
        StringBuilder builder = new StringBuilder();
        builder.append("外设类型："+cmd.deviceStr());
        builder.append("\r\n");

        System.out.println(cmd.leftSize());

        builder.append("终端->ADAS：ADAS实时数据指令");
        builder.append("\r\n");
        builder.append("车速（单位 km/h。范围 0~250）："+cmd.readInt(1));
        builder.append("\r\n");
        cmd.moveIndex(1);//预留
        builder.append("里程（单位0.1km）："+cmd.readInt(4));
        builder.append("\r\n");
        cmd.moveIndex(2);//预留

        builder.append("高程（海拔高度，单位为米（m））："+cmd.readInt(2));
        builder.append("\r\n");
        builder.append("纬度：" + cmd.readInt(4));
        builder.append("\r\n");
        builder.append("经度：" + cmd.readInt(4));
        builder.append("\r\n");
        builder.append("日期：" + cmd.readBCD(6));
        builder.append("\r\n");

        int data = cmd.readInt(2);
        builder.append("车辆状态：(" + data + ")");
        builder.append("\r\n");
        builder.append("    ACC状态(0：关闭，1：打开):"+(data&0x01));
        builder.append("\r\n");
        builder.append("    左转向状态(0：关闭，1：打开):"+((data>>1)&0x01));
        builder.append("\r\n");
        builder.append("    右转向状态(0：关闭，1：打开):"+((data>>2)&0x01));
        builder.append("\r\n");
        builder.append("    雨刮器状态(0：关闭，1：打开):"+((data>>3)&0x01));
        builder.append("\r\n");
        builder.append("    制动状态(0：未制动，1：制动):"+((data>>4)&0x01));
        builder.append("\r\n");
        builder.append("    插卡状态(0：未插卡，1：已插卡):"+((data>>5)&0x01));
        builder.append("\r\n");
        builder.append("    定位状态(0：未定位，1：已定位):"+((data>>10)&0x01));
        builder.append("\r\n");
        return builder.toString();
    }


    private String handleCmd51(JS_ATL_2017Cmd cmd) {
        StringBuilder builder = new StringBuilder();
        builder.append("外设类型："+cmd.deviceStr());
        builder.append("\r\n");

        if (cmd.leftSize() == 10){
            builder.append("终端->外设：传输多媒体数据应答");
            builder.append("\r\n");
            builder.append("消息ID："+cmd.readInt(1));
            builder.append("\r\n");
            builder.append("多媒体ID："+cmd.readInt(4));
            builder.append("\r\n");
            builder.append("总包数："+cmd.readInt(2));
            builder.append("\r\n");
            builder.append("包序号："+cmd.readInt(2));
            builder.append("\r\n");
            builder.append("传输结果："+(cmd.readInt(1) == 0?"0(成功)":"1(失败)"));
            builder.append("\r\n");
        }else {
            builder.append("外设->终端：传输多媒体数据");
            builder.append("\r\n");
            builder.append("消息ID：" + cmd.readInt(1));
            builder.append("\r\n");
            builder.append("多媒体ID：" + cmd.readInt(4));
            builder.append("\r\n");
            builder.append("总包数：" + cmd.readInt(2));
            builder.append("\r\n");
            builder.append("包序号：" + cmd.readInt(2));
            builder.append("\r\n");
            builder.append("多媒体数据：" + cmd.readBCD(cmd.leftSize()));
            builder.append("\r\n");
        }

        return builder.toString();
    }

    private String handleCmd2F(JS_ATL_2017Cmd cmd) {
        StringBuilder builder = new StringBuilder();
        builder.append("外设类型："+cmd.deviceStr());
        builder.append("\r\n");

        builder.append("如果为终端->外设,该命令为询问设备是否存在；");
        builder.append("\r\n");
        builder.append("如果为外设->终端,该命令为应答设备存在");
        builder.append("\r\n");

        return builder.toString();
    }

    /**
     * 传输多媒体数据
     * @param cmd
     * @return
     */
    private String handleCmd50(JS_ATL_2017Cmd cmd) {

        StringBuilder builder = new StringBuilder();
        builder.append("外设类型："+cmd.deviceStr());
        builder.append("\r\n");

        System.out.println(cmd.leftSize());

        if (cmd.leftSize() == 5){
            builder.append("终端->外设：请求多媒体数据");
            builder.append("\r\n");
            builder.append("消息ID："+cmd.readInt(1));
            builder.append("\r\n");
            builder.append("多媒体ID："+cmd.readInt(4));
            builder.append("\r\n");
        }else {
            builder.append("外设->终端：请求多媒体数据应答");
            builder.append("\r\n");
        }

        return builder.toString();
    }

    /**
     * DMS报警
     * @return
     * @param cmd
     */
    private String handleCmd36(JS_ATL_2017Cmd cmd) {
        StringBuilder builder = new StringBuilder();
        builder.append("外设类型：" + cmd.deviceStr());
        builder.append("\r\n");

        byte device = cmd.device();

        if (cmd.leftSize() == 0) {
            builder.append("终端->外设：报警应答");
        } else
            if (cmd.device() == DEVICE_DMS) {
            builder.append("DMS->终端：报警");
            builder.append("\r\n");
            builder.append("报警ID：" + cmd.readInt(4));
            builder.append("\r\n");
            int flag = cmd.readInt(1);
            builder.append("报警标识(" + flag + "):");
            switch (flag) {
                case 0x00:
                    builder.append("标识不可用");
                    break;
                case 0x01:
                    builder.append("开始标识");
                    break;
                case 0x02:
                    builder.append("结束标识");
                    break;
                default:
                    builder.append("未知");
                    break;
            }
            builder.append("\r\n");
            int type = cmd.readInt(1);
            builder.append("报警/事件类型(" + type + ")：");
            switch (type) {
                case 0x01:
                    builder.append("疲劳驾驶报警");
                    break;
                case 0x02:
                    builder.append("接听电话报警");
                    break;
                case 0x03:
                    builder.append("抽烟报警");
                    break;
                case 0x04:
                    builder.append("分神驾驶报警");
                    break;
                case 0x05:
                    builder.append("驾驶员异常报警");
                    break;
                case 0x06:
                    builder.append("未戴口罩");
                    break;
                case 0x07:
                    builder.append("DMS摄像头失效（遮挡）");
                    break;
                case 0x10:
                    builder.append("主动抓拍事件");
                    break;
                case 0x11:
                    builder.append("驾驶员变更事件");
                    break;
                case 0x12:
                    builder.append("驾驶员身份识别");
                    break;
                case 0x1E:
                    builder.append("DMS摄像头故障");
                    break;
                case 0x1F:
                    builder.append("红外阻断报警");
                    break;
                default:
                    builder.append("未知");
                    break;
            }

            builder.append("\r\n");
            builder.append("疲劳程度：" + cmd.readInt(1));
            builder.append("\r\n");
            cmd.moveIndex(4);
            builder.append("车速（km/s）：" + cmd.readInt(1));
            builder.append("\r\n");
            builder.append("高程：" + cmd.readInt(2));
            builder.append("\r\n");
            builder.append("纬度：" + cmd.readInt(4));
            builder.append("\r\n");
            builder.append("经度：" + cmd.readInt(4));
            builder.append("\r\n");
            builder.append("日期：" + cmd.readBCD(6));
            builder.append("\r\n");
            builder.append("车辆状态：(" + cmd.readInt(2) + ")");
            builder.append("\r\n");

            int warnCount = cmd.readInt(1);
            builder.append("报警多媒体信息列表总数：" + warnCount);
            builder.append("\r\n");
            for (int i = 0; i < warnCount; i++) {
                int mediaType = cmd.readInt(1);
                switch (mediaType) {
                    case 0x00:
                        builder.append("  多媒体类型(0)：图片");
                        break;
                    case 0x01:
                        builder.append("  多媒体类型(1)：音频");
                        break;
                    case 0x02:
                        builder.append("  多媒体类型(2)：视频");
                        break;
                }
                builder.append("\r\n");
                builder.append("  多媒体ID：" + cmd.readInt(4));
                builder.append("\r\n");
            }
        } else if (device == DEVICE_ADAS) {
            builder.append("ADAS->终端：报警");
            builder.append("\r\n");
            builder.append("报警ID：" + cmd.readInt(4));
            builder.append("\r\n");
            int flag = cmd.readInt(1);
            builder.append("报警标识(" + flag + "):");
            switch (flag) {
                case 0x00:
                    builder.append("标识不可用");
                    break;
                case 0x01:
                    builder.append("开始标识");
                    break;
                case 0x02:
                    builder.append("结束标识");
                    break;
                default:
                    builder.append("未知");
                    break;
            }
            builder.append("\r\n");
            int type = cmd.readInt(1);
            builder.append("报警/事件类型(" + type + ")：");
            switch (type) {
                case 0x01:
                    builder.append("前向碰撞报警");
                    break;
                case 0x02:
                    builder.append("车道偏离报警");
                    break;
                case 0x03:
                    builder.append("车距过近报警");
                    break;
                case 0x04:
                    builder.append("行人碰撞报警");
                    break;
                case 0x05:
                    builder.append("频繁变道报警");
                    break;
                case 0x06:
                    builder.append("道路标识超限报警");
                    break;
                case 0x08:
                    builder.append("ADAS摄像头失效（遮挡）");
                    break;
                case 0x10:
                    builder.append("道路标志识别事件");
                    break;
                case 0x11:
                    builder.append("主动抓拍事件");
                    break;
                case 0x1F:
                    builder.append("ADAS摄像头故障(损坏、在线检测失败等)");
                    break;
                default:
                    builder.append("未定义");
                    break;
            }

            builder.append("\r\n");
            builder.append("前车车速（单位Km/h，范围0~250，仅报警类型为0x01和0x02时有效）：" + cmd.readInt(1));
            builder.append("\r\n");
            builder.append("前车/行人距离（单位100ms，范围0~100，仅报警类型为0x01、0x02和0x04时有效）：" + cmd.readInt(1));
            builder.append("\r\n");
            builder.append("偏离类型（0x01：左侧偏离" + "0x02：右侧偏离" + "仅报警类型为0x02时有效）：" + cmd.readInt(1));
            builder.append("\r\n");
            builder.append("道路标志识别类型（0x01：限速标志 0x02：限高标志0x03：限重标志，仅报警类型为0x06和0x10时有效）：" + cmd.readInt(1));
            builder.append("\r\n");
            builder.append("道路标志识别数据（识别到道路标志的数据）：" + cmd.readInt(1));
            builder.append("\r\n");
            builder.append("车速（单位Km/h。范围0~250）：" + cmd.readInt(1));
            builder.append("\r\n");
            builder.append("高程：" + cmd.readInt(2));
            builder.append("\r\n");
            builder.append("纬度：" + cmd.readInt(4));
            builder.append("\r\n");
            builder.append("经度：" + cmd.readInt(4));
            builder.append("\r\n");
            builder.append("日期：" + cmd.readBCD(6));
            builder.append("\r\n");

            builder.append("车辆状态：(" + cmd.readInt(2) + ")");
            builder.append("\r\n");

            int warnCount = cmd.readInt(1);
            builder.append("报警多媒体信息列表总数：" + warnCount);
            builder.append("\r\n");
            for (int i = 0; i < warnCount; i++) {
                int mediaType = cmd.readInt(1);
                switch (mediaType) {
                    case 0x00:
                        builder.append("  多媒体类型(0)：图片");
                        break;
                    case 0x01:
                        builder.append("  多媒体类型(1)：音频");
                        break;
                    case 0x02:
                        builder.append("  多媒体类型(2)：视频");
                        break;
                }
                builder.append("\r\n");
                builder.append("  多媒体ID：" + cmd.readInt(4));
                builder.append("\r\n");
            }
        }

        return builder.toString();
    }

}
